//CalculatorClient.hpp
#pragma once
#include "Sock.hpp"
#include "Protocol.hpp"
class CalculatorClient
{
public:
    // 处理算术运算式转换时需要（Analysis）
    enum
    {
        LEFT,
        RIGHT,
        OP,
    };

    // 将字符串转换成Request格式
    Request Analysis(string expression)
    {
        // 用来存储左操作数和右操作数
        string left, right;
        // 存储运算符
        char op;
        // 迭代字符串
        int i = 0;
        // 一开始肯定是左操作数
        int status = LEFT;
        while (i < expression.size())
        {
            switch (status)
            {
            case LEFT:
                if (isdigit(expression[i]))
                {
                    // 如果是数字就放入左操作数中
                    left.push_back(expression[i++]);
                }
                else
                {
                    // 一旦左操作数结束，肯定是运算符
                    status = OP;
                }
                break;
            case OP:
                op = expression[i++];
                // 运算符只有一个，所以说下一个就是右操作数
                status = RIGHT;
                break;
            case RIGHT:
                if (isdigit(expression[i]))
                    right.push_back(expression[i++]);
                break;
            }
        }

        // cout<<"req._x"<<left<<endl;
        // cout<<"req._y"<<right<<endl;
        // cout<<"req._op"<<op<<endl;

        //将其放入到Request中
        Request req;
        req._x = stoi(left);
        req._y = stoi(right);
        req._op = op;

        return req;
    }

    void Init()
    {
        // 1.创建套接字
        _sock.Socket();
        _socket = _sock.GetSock();
        LogMessage(Debug, "client Init done");
    }

    void Start(string serverip, uint16_t serverport)
    {
        while (1)
        {

            // 2.连接服务器
            int n = _sock.Connect(serverip, serverport);
            // 返回值0为连接成功，-1为失败
            if (n < 0)
            {
                LogMessage(Warning, "connect error,try again");
                sleep(1);
                continue;
            }
            else
            {
                LogMessage(Debug, "client connect done");
                break;
            }
        }

        // 3.正式开始和服务器通信
        while (1)
        {
            cout << "Enter#";
            string buff;

            // 获取一行数学算式
            getline(cin, buff);
            // Request是用来进行处理请求的序列化和反序列化的
            Request req = Analysis(buff);


            // 1.序列化
            string payload;
            req.Serialize(payload);
            // 2.添加报头
            string str = AddHeader(payload);
            // 3.发送
            send(_socket, str.c_str(), str.size(), 0);
            LogMessage(Debug, "send success");
            // 4.接收
            string storage_packaging;//存储所有这次读取完后剩余的报文
            string rec;//本次完整的报文
        AGAIN:
            //读数据  
            //ReadPackage的后两个参数是引用,返回值是报文中有效载荷的大小
            int payloadlen= ReadPackage(_socket, storage_packaging, rec);
            if (payloadlen == 0)
            {
                LogMessage(Warning, "read fail,the server already close");
                return;
            }
            else if (payloadlen< 0)
            {
                LogMessage(Information, "analysis fail,try again");
                goto AGAIN;
            }
            else
            {
                // 5.去报头
                string info = DelHeader(rec, payloadlen);
                // 6.反序列化
                Response res;
                res.Deserialization(info);
                cout << "result:" << res._result << "code:" << res._code << endl;
            }
        }
    }

    Sock _sock;      // 进行TCP通信的封装
    int _socket; // 监听需要的描述符
};